package sample;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.geometry.Orientation;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import sample.util.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;
import javafx.util.Duration;
import sample.util.Alert;

import java.awt.Font;
import java.io.File;
import java.net.MalformedURLException;
import java.util.concurrent.atomic.AtomicInteger;

/**

 * @name      :SceneBuilder

 * @Description: a scene builder class for all static scene generation
 * the sequence of a new button created
 1. implement the main function on a pane
 2. add some supplements with the main part in a scene
 3. popup a stage to show it
 */
public class SceneBuilder {
    /**

     * @name      :MainScene

     * @param     :[]

     * @return    :javafx.scene.Scene

     * @Description: create the main scene for stage to show

    */
    public static Scene MainScene() throws MalformedURLException {
        GridPane grid=new GridPane();

        grid.add(ButtonGenerator.paint(),0,0);
        grid.add(ButtonGenerator.game(),0,1);
        grid.add(ButtonGenerator.web(),1,0);
        grid.add(ButtonGenerator.like(),1,1);

        return new Scene(grid);
    }

    /**

     * @name      :getSharp

     * @param     :[]

     * @return    :javafx.scene.Parent

     * @Description:

    */
    public static Parent getSharp(){
        Pane pane=new Pane();
        pane.setMinWidth(50);
        pane.setMinHeight(50);
        Line[] row=new Line[2];
        Line[] col=new Line[2];
        Ctl.RowLineSet(pane,row,3);
        Ctl.ColLineSet(pane,col,3);
        pane.getChildren().addAll(row[0],row[1],col[0],col[1]);
        return pane;
    }

    /**

     * @name      :NullScene

     * @param     :[]

     * @return    :javafx.scene.Scene

     * @Description: generate a null scene for unimplemented or not plan to do function or module

    */
    public static Scene NullScene(){
        Text text=new Text("busy implementing it now!");
        text.setFont(javafx.scene.text.Font.font(Font.MONOSPACED));
        text.setFill(Color.RED);
        text.setTextAlignment(TextAlignment.CENTER);
        Button msg=new Button("",text);
        msg.setContentDisplay(ContentDisplay.TOP);
        Tooltip tip=new Tooltip();
        tip.setText("别看我 有本事联系作者");
        tip.setTextAlignment(TextAlignment.CENTER);
        msg.setTooltip(tip);
        return new Scene(new BorderPane(msg),200,150);
    }

    /**

     * @name      :OrientationSplitPane

     * @param   o orientation

     * @return    :javafx.scene.control.SplitPane

     * @Description: get specific orientation splitPane
     * for bean-style programming

    */
    public static SplitPane OrientationSplitPane(Orientation o){
        SplitPane sp=new SplitPane();
        sp.setOrientation(o);
        return sp;
    }
    /**

     * @name      :HorizonPane

     * @param     index

     * @return    :javafx.scene.control.SplitPane

     * @Description: for bundle generation of forEach method or other functional style method

    */
    public static SplitPane HorizonPane(int index){
        SplitPane sp=SceneBuilder.OrientationSplitPane(Orientation.HORIZONTAL);
        if(index<=0)return sp;
        while(index--!=0){
            SplitPane p=new SplitPane();
//            p.getItems().add(new Pane());
            p.setMinHeight(50);
            p.setMinWidth(50);
            sp.getItems().add(p);
        }
        return sp;
    }

    /**

     * @name      :ImportScene

     * @param     :[]

     * @return    :javafx.scene.Scene

     * @Description: for file import when in painting

    */
    public static Scene ImportScene(){
//        final AtomicReference<StringBuilder> dot= new AtomicReference<>();
//        StringProperty dots=new SimpleStringProperty("searching for file");
        Text text=new Text();
        text.setFill(Color.PURPLE);
        text.setTextAlignment(TextAlignment.CENTER);
        final String dot="searching for file";
        text.setText(dot);
        AtomicInteger times=new AtomicInteger(0);
        Timeline action=new Timeline(new KeyFrame(Duration.millis(200),e->{
            if(times.getAndIncrement()!=19){
                switch(text.getText().length()-dot.length()){
                    case 0,1,2,3 -> text.setText(text.getText()+"·");
                    case 4-> text.setText("searching for file");
                }
            }else{
                text.setText("No file matched found!");
            }
        }));
        action.setCycleCount(20);
        action.play();
        return new Scene(new BorderPane(text),250,150);
    }

    /**

     * @name      :HeartBoard

     * @param     :[]

     * @return    :javafx.scene.Scene

     * @Description: draw a heart

    */
    public static Scene HeartBoard(){
        return new Scene(HeartPane.GenerateStaticHeart());
    }


    /**

     * @name      :PaintingPlace

     * @param     :[]

     * @return    :void

     * @Description:  get the painting place for stage to show

    */
    public static void PaintingPlace(){
        Stage paint=new Stage();
        SplitPane split=new SplitPane();
        split.setOrientation(Orientation.VERTICAL);

//        DrawPane dp=;

        MenuBar painter=new MenuBar();
        Menu size=Ctl.MenuWithText("LineWidth");
//        size.getItems().add(new CheckMenuItem("?"));
        Menu color=Ctl.MenuWithText("LineColor");// some color and RGB
        Menu fileOp=Ctl.MenuWithText("File");// save import
        Menu undo=Ctl.MenuWithText("Undo");// cancel the series op after the last save
        painter.getMenus().addAll(fileOp,color,size,undo);

        // todo Menu initialization

        split.getItems().addAll(painter,new DrawPane());
//        System.out.println(split.getItems().get(1));
        Ctl.MenuAddCommonItemWithText(color,"Black","Red","Green","Yellow","...");
        Ctl.MenuAddCommonItemWithText(fileOp,"save","save as...","import");
        Ctl.MenuAddCommonItemWithText(undo,"undo","clear");
        DrawPane dp=(DrawPane) split.getItems().get(1);

        // Todo Menu func implement

        DrawPane.MenuStrokeWidth(size,dp);
        DrawPane.MenuColorAction(color,4,dp);
        fileOp.getItems().get(0).setOnAction(e-> dp.save());

        Ctl.NullMenuItemOperation(fileOp.getItems().get(1));// Save as... NullOp
        fileOp.getItems().get(2).setOnAction(e-> Ctl.MessageBox("Import File",SceneBuilder.ImportScene(),15).show());
        undo.getItems().get(0).setOnAction(e-> dp.undo());
        undo.getItems().get(1).setOnAction(e-> dp.clear());

        // Set ShortCut key combo
        KeyCombination keyCombo=new KeyCodeCombination(KeyCode.S,KeyCodeCombination.SHORTCUT_DOWN);
        KeyCombination EasterEgg=new KeyCodeCombination(KeyCode.W,KeyCodeCombination.SHORTCUT_DOWN);
        Scene scene=new Scene(split);
        scene.getAccelerators().put(keyCombo, dp::save);
        scene.getAccelerators().put(EasterEgg, dp::egg);
        dp.setOnclickCroatian(DrawPane.Croatian(true));
        File cssFile=new File("src/css/allSrc.css");
        try {
            scene.getStylesheets().add(cssFile.toURI().toURL().toString());
        } catch (MalformedURLException e) {
            new Alert("Error",5);
        }
        paint.setScene(scene);
        paint.setTitle("Painting");
        paint.show();
        dp.requestFocus();
    }

    /**

     * @name      :Like

     * @param     :[]

     * @return    :void

     * @Description: click to  create the like stage

    */
    public static void Like(){
        Stage stage=new Stage();
        stage.setScene(WebView());
        ((WebScrollPane)stage.getScene().getRoot()).setStage(stage).fitStageSize(500);
        try {
            stage.getScene().getStylesheets()
                    .add(new File("src/css/index.css").toURI().toURL().toString());
        } catch (MalformedURLException ignored) {}
        stage.setTitle("like this proj");
//        stage.getScene().getRoot().setStyle("-fx-alignment: center");
        stage.show();
    }

    /**

     * @name      :Web

     * @param     :[]

     * @return    :void

     * @Description: click to create web stage

    */
    public static void Web(){
        Stage stage=new Stage();
        stage.setTitle("Web mini Explorer");
        stage.setScene(WebInit());
//        System.out.println(((WebScrollPane)stage.getScene().getRoot()).toString());
        ((WebScrollPane)stage.getScene().getRoot()).setStage(stage);
//        stage.setWidth(800);
//        stage.setHeight(600);
        stage.show();
        ((WebScrollPane)stage.getScene().getRoot()).searchBarRequestFocus();
    }
    public static Scene WebView(){
        return new Scene(new WebScrollPane().search(engine.main));
    }
    public static Scene WebView(String page){
        return new Scene(new WebScrollPane().search(page,engine.raw));
    }
    public static Scene WebInit(){
        return new Scene(new WebScrollPane().search(engine.start));
    }
    /**

     * @name      :GamePlace

     * @param     :[]

     * @return    :void

     * @Description: click to  create the gameSpace stage

    */
    public static void GamePlace() throws MalformedURLException {
        Stage stage=new Stage();
        GridPane grid=new GridPane();
        grid.add(ButtonGenerator.tic(),0,0);
        grid.add(ButtonGenerator.snake(),1,0);
//        HBox cont=new HBox(ButtonGenerator.tic()
//                ,ButtonGenerator.snake());
//        HBox cont=new HBox(ButtonGenerator.tic());
        stage.setScene(new Scene(grid));
        stage.setTitle("GameSpace");
        stage.show();
    }
    /**

     * @name      :TicPlace

     * @param     :[]

     * @return    :void

     * @Description: click to  create the tic stage

    */
    public static void TicPlace(){
        Stage stage=new Stage();
        stage.setTitle("Tic-Tac-Toe");
        stage.setScene(SceneBuilder.Tic());
        stage.show();
    }

    public static Scene Tic() {
        try {
            return new TicTacToe(new Pane());
        } catch (MalformedURLException e) {
            new Alert("Tic miss",5).show();
            return null;
        }
    }

}

